//SmallIntWithIncrDecr.cc (modified)

#include <iostream>
#include <cstdlib>
using namespace std;
class SmallInt {
  int value;
  bool rangeCheck(int i);
public:
  static const int MAX = 255;
  static const int MIN = 0;
  explicit SmallInt(int ival = 0); 
  // explicit suppress implicit conversion by the compiler
  SmallInt(const SmallInt& other);
  SmallInt& operator=(const SmallInt& other);
  SmallInt& operator=(const int i);
  //unsafe implicit conversion:
  operator int() const {
    cout << "operator int() const {" << endl;
    // implicit conversion
    return value;
  } //(B)
  SmallInt& operator++();
  SmallInt& operator--();
  const SmallInt operator++(int);
  const SmallInt operator--(int);
  friend ostream& operator<<(ostream& os, const SmallInt& s);
};

//constructor:
inline SmallInt::SmallInt(int ival) {
  cout << "SmallInt::SmallInt(int ival) {" << endl;
  if (rangeCheck(ival)) {
    value = ival;
  } else {
    cout << "Error: Range of SmallInt violated" << endl;
  }
}

//copy constructor:
inline SmallInt::SmallInt(const SmallInt& other) {
  cout << "SmallInt::SmallInt(const SmallInt& other) {" << endl;
  value = other.value;
}

//copy assignment operator:
inline SmallInt& SmallInt::operator=( const SmallInt& other ) {
  cout << "SmallInt& SmallInt::operator=( const SmallInt& other ) {" << endl;
  if ( this != & other ) {
    value = other.value;
  }
  return *this;
}

//assignment from an int:
inline SmallInt& SmallInt::operator=( const int i ) {
  cout << "SmallInt& SmallInt::operator=( const int i ) {" << endl;
  if (rangeCheck(i)) {
    value = i;
  } else {
    cout << "Error: Range of SmallInt violated" << endl;
  }
  return *this;
}

//prefix increment operator:
inline SmallInt& SmallInt::operator++() {
  cout << "SmallInt& SmallInt::operator++() {" << endl;
  if (value < MAX) {
    value ++;
  } else {
    cout << "Error: Range of SmallInt violated" << endl;
  }
  return *this;
}

//prefix decrement operator:
inline SmallInt& SmallInt::operator--() {
  cout << "SmallInt& SmallInt::operator--() {" << endl;
  if (value> MIN) {
    value --;
  } else {
    cout << "Error: Range of SmallInt violated" << endl;
  }
  return *this;
}

//postfix increment operator:
inline const SmallInt SmallInt::operator++(int) {
  cout << "SmallInt SmallInt::operator++(int) {" << endl;
  SmallInt oldValue = *this;
  ++(*this);
  return oldValue;
}

//postfix decrement operator:
inline const SmallInt SmallInt::operator--(int) {
  cout << "SmallInt SmallInt::operator--(int) {" << endl;
  SmallInt oldValue = *this;
  --(*this);
  return oldValue;
}

//range check function:
inline bool SmallInt::rangeCheck(int i) {
  cout << "SmallInt::rangeCheck(int i) {" << endl;
  if ((i < MIN) || (i > MAX)) {
    return false;
  }
  return true;
}

//overload for the output stream operator:
ostream& operator<<(ostream& os, const SmallInt& s) {
  os << s.value;
  return os;
}

int main() {
  SmallInt si( 3);
  cout << endl;

  cout << "A: si + 3.14159" << endl;
  cout << si + 3.14159 << endl << endl; // 6.14159

  cout << "B: ++si" << endl; 
  cout << ++si << endl << endl; // 4

  cout << "C: si++" << endl;
  cout << si++ << endl << endl; // 4

  cout << "D: si" << endl;
  cout << si << endl << endl;   // 5

  cout << "E: --si" << endl;
  cout << --si << endl << endl; // 4

  cout << "F: si" << endl;
  cout << si << endl << endl;   // 4

  cout << "G: si--" << endl;
  cout << si-- << endl << endl; // 4

  cout << "H: si" << endl;
  cout << si << endl << endl;   // 3

  cout << "I: ++si + 5" << endl;
  cout << ++si + 5 << endl << endl;   // 9

  cout << "J: si" << endl;
  cout << si << endl << endl;   // 4

  cout << "si++ + 5" << endl;
  cout << si++ + 5 << endl << endl; // 9

  cout << "K: si" << endl;
  cout << si << endl << endl;   // 5

  si = 255;
  cout << si << endl << endl;
  si++; // range violated, error message
  cout << endl;
  
  si = 300; // range violated, error message
  cout << endl;
  
  cout << si + 400 << endl << endl; //(C)       

  si = 17;
  si = si + si;
  cout << "L: si" << endl;
  cout << si << endl << endl;

  SmallInt si2(si + 3);
  cout << "M: si2" << endl;
  cout << si2 << endl << endl;

  /*
   SmallInt si3 = si2 + 5;
   error: conversion from ‘int’ to non-scalar type ‘SmallInt’ requested
   cout << "N: si3" << endl;
   cout << si3 << endl;
  */
  return 0;
}

/*
output:

SmallInt::SmallInt(int ival) {
SmallInt::rangeCheck(int i) {

A: si + 3.14159
operator int() const {
6.14159

B: ++si
SmallInt& SmallInt::operator++() {
4

C: si++
SmallInt SmallInt::operator++(int) {
SmallInt::SmallInt(const SmallInt& other) {
SmallInt& SmallInt::operator++() {
4

D: si
5

E: --si
SmallInt& SmallInt::operator--() {
4

F: si
4

G: si--
SmallInt SmallInt::operator--(int) {
SmallInt::SmallInt(const SmallInt& other) {
SmallInt& SmallInt::operator--() {
4

H: si
3

I: ++si + 5
SmallInt& SmallInt::operator++() {
operator int() const {
9

J: si
4

si++ + 5
SmallInt SmallInt::operator++(int) {
SmallInt::SmallInt(const SmallInt& other) {
SmallInt& SmallInt::operator++() {
operator int() const {
9

K: si
5

SmallInt& SmallInt::operator=( const int i ) {
SmallInt::rangeCheck(int i) {
255

SmallInt SmallInt::operator++(int) {
SmallInt::SmallInt(const SmallInt& other) {
SmallInt& SmallInt::operator++() {
Error: Range of SmallInt violated

SmallInt& SmallInt::operator=( const int i ) {
SmallInt::rangeCheck(int i) {
Error: Range of SmallInt violated

operator int() const {
655

SmallInt& SmallInt::operator=( const int i ) {
SmallInt::rangeCheck(int i) {
operator int() const {
operator int() const {
SmallInt& SmallInt::operator=( const int i ) {
SmallInt::rangeCheck(int i) {
L: si
34

operator int() const {
SmallInt::SmallInt(int ival) {
SmallInt::rangeCheck(int i) {
M: si2
37

*/
